#include "Tools/sockcompat.h"
#include <iostream>
#include <GeeJoan/NetWorkPackage.pb.h>
#include <GeeJoan/AuthModule.pb.h>
#include <GeeJoan/IoTModule.pb.h>
#include <GeeJoan/ErrorModule.pb.h>
#include <chrono>
#include <Business/internaltypes.h>
#include <Tools/CommonTool.h>


#define IPADDRESS "127.0.0.1"
#define PORT 12345
#define MAXLINE 1024
#define max(a, b) (a>b) ? a : b


static void handle_connection(int sockfd);

using namespace GeeJoan::Protocol;

enum LANGCode{
    CHINESE = 1 ,
    ENGLISH = 2 ,
};
int currentLangCode = ENGLISH ; //
int64_t getTimeMicro()
{
    std::chrono::time_point<std::chrono::system_clock> p = std::chrono::system_clock::now();
    return std::chrono::duration_cast<std::chrono::microseconds>( p.time_since_epoch()).count();
}


int64_t getTimeMilli()
{
    return getTimeMicro() / 1000;
}

int main(int argc, char *argv[])
{
    int connfd = 0;
    int clen = 0;
    struct sockaddr_in client;
    if (argc < 2)
    {
        printf( "Uasge: %s [server IP address]\n", argv[0] );
        return -1;
    }

    client.sin_family = AF_INET;
    client.sin_port = htons( PORT );
    client.sin_addr.s_addr = inet_addr( argv[1] );
    connfd = socket( AF_INET, SOCK_STREAM, 0 );
    if (connfd < 0)
    {
        perror( "socket" );
        return -1;
    }

    if (connect( connfd, (struct sockaddr *) &client, sizeof( client )) < 0)
    {
        perror( "connect" );
        return -1;
    }

    std::cout << "client Run ... " << std::endl;
    std::cout << "input " << RED << "`menu`" << RESET << " open Menu List ... " << std::endl;
    std::cout << "input " << RED << "`quit`" << RESET << " Quit This Progarm ... " << std::endl;

    handle_connection( connfd );
    google::protobuf::ShutdownProtobufLibrary();
    return 0;
}

std::string username;
std::string token;
int64_t taskid_ = 1;
//std::string password;

/**
 * @brief 回包事件
 * @param data 数据
 * @param len  数据长度
 * @return
 */
int ResposePackageEvent(uint8_t *data, int len)
{

    NetWork::NetWorkPackageRespose networkPackageResp;
    if (!networkPackageResp.ParseFromArray( data, len ))
    {
        // 不支持
        write( STDOUT_FILENO, "proto deserial error\r\n", 22 );

    } else
    {
        //支持的类型
        std::cout << YELLOW << "Respose : code = " << networkPackageResp.code()
                  << ", mod = " << networkPackageResp.type_m() << " , type = " << networkPackageResp.type_sub()
                  << " , taskid = " << networkPackageResp.taskid()
                  << " , body = " << StringToHex( networkPackageResp.body()) << RESET << std::endl;
    }
//            std::cout << " taskid resp = " << networkPackageResp.taskid() << std::endl;

    if (networkPackageResp.code() == 500)
    {
        Error::ErrorMessage errorMessage;

        if (errorMessage.ParseFromString( networkPackageResp.body()))
        {
            std::cout << RED << "ErrorMsg : " << errorMessage.errmsg() << RESET << std::endl;
        }

    }

    if (networkPackageResp.code() != 200)
    {
        return -1;
    }

    if (networkPackageResp.type_m() == NetWork::NetWorkPackageModel::AuthMod)
    {
        switch (networkPackageResp.type_sub())
        {
            case 1:
            {
                if (networkPackageResp.code() == 200)
                {
                    std::cout << "Register " << GREEN << "Success !" << RESET << std::endl;
                }
                break;
            }
            case 2:
            {
                Auth::LoginRespose loginRespose;
                if (loginRespose.ParseFromArray( networkPackageResp.body().c_str(),
                                                 networkPackageResp.body().length()));
                {
                    // 解包成功
                    token = loginRespose.token();
                    std::cout << "Login " << GREEN << "Success " << RESET << std::endl;
                    std::cout << "Your Token = " << GREEN << token << RESET << std::endl;
                }
                break;
            }

            case 3:
            {
                std::cout << " Logout " << GREEN << "Success " << RESET << networkPackageResp.code() << std::endl;
                break;
            }

            case 4:
            {
                std::cout << " head code = " << networkPackageResp.code() << std::endl;
                break;
            }
            case 5:
            {
                std::cout << "change code = " << networkPackageResp.code() << std::endl;
                Auth::ChangePasswordRespose changePasswordRespose;
                if (changePasswordRespose.ParseFromArray( networkPackageResp.body().c_str(),
                                                          networkPackageResp.body().length()))
                {
                    token = changePasswordRespose.newtoken();
                    std::cout << "your new token = " << GREEN << token << RESET << std::endl;
                }
                break;
            }
        }
    } else if (networkPackageResp.type_m() == NetWork::NetWorkPackageModel::IOTMod)
    {
        switch (networkPackageResp.type_sub())
        {
            case 1:
            {
                std::cout << "Upload Data : " << GREEN << " Success " << RESET << std::endl;
                break;
            }
            case 2:
            {
                std::cout << "FindData : " << GREEN << " Success " << RESET << std::endl;
                IoT::FindSensorDataRespose findSensorDataRespose;

                if (!findSensorDataRespose.ParseFromString( networkPackageResp.body()))
                {
                    // 解析失败
                    std::cout << RED << "ERROR : deserial findSensorDataRespose Fail ! " << RESET << std::endl;
                    break;
                }

                // 解析成功
                std::cout << "Find Data : gatewayid = " << YELLOW << findSensorDataRespose.gatewayid() << RESET
                          << ", deviceid  = " << YELLOW << findSensorDataRespose.deviceid() << RESET
                          << ", size = " << YELLOW << findSensorDataRespose.datas().size() << RESET << std::endl;
                for (int i = 0; i < findSensorDataRespose.datas().size(); ++i)
                {
                    std::string tempData =findSensorDataRespose.datas( i ).data();
                    std::cout << "Datas[" << i << "]"
                              << " : key = " <<  YELLOW << findSensorDataRespose.datas( i ).key() << RESET
                              << " , data(Src) = " << YELLOW <<tempData << RESET
                              << " , data(HEX) = " << YELLOW <<StringToHex(tempData) << RESET
                              << " , time = " << YELLOW << findSensorDataRespose.datas( i ).time() << RESET
                              << std::endl;
                }
                break;
            }

            case IOT_CONTROL_DEVICE:
            {
//                std::cout << " control code = " << networkPackageResp.code() << std::endl;
                std::cout <<" Control Send : "<< GREEN <<"SUCCESS" <<RESET<<std::endl;
                break;
            }

            case IOT_CONTROL_LISTERNER:
            {
//                std::cout << " lister code = " << networkPackageResp.ode() << std::endl;
                IoT::ControlDeviceListerner controlDeviceListerner;

                if (!controlDeviceListerner.ParseFromString(networkPackageResp.body()))
                {
                    std::cout << RED << "ERROR : deserial controlDeviceListerner Fail ! " << RESET << std::endl;
                    break;
                }

                std::cout <<"ListernerEvent : taskCode = "<<YELLOW << controlDeviceListerner.taskcode() <<RESET
                          << " , data = " << YELLOW << controlDeviceListerner.data() << RESET
                          << " , time = " << YELLOW << controlDeviceListerner.time()<<RESET <<std::endl;

                break;
            }


            case IOT_CONTROL_ACK:
            {
                std::cout <<"Ack : " <<GREEN << "SUCCESS "<<RESET<<std::endl;
                break;
            }
            case IOT_CONTROL_ACK_LISTERNER:
            {
                IoT::ControlDeviceAckListerner controlDeviceAckListerner;
                if(!controlDeviceAckListerner.ParseFromString(networkPackageResp.body()))
                {
                    std::cout << RED << "ERROR : deserial controlDeviceAckListerner Fail ! " << RESET << std::endl;
                    break;
                }

                std::cout <<"AckEvent : taskCode = "<<YELLOW << controlDeviceAckListerner.taskcode() <<RESET
                          << " , errcode = " << YELLOW << controlDeviceAckListerner.errcode() << RESET
                          << " , errormsg = " << YELLOW << controlDeviceAckListerner.errormsg()<<RESET
                          << " , time = " << YELLOW << controlDeviceAckListerner.time()<<RESET <<std::endl;
                break;
            }
            case IOT_FIND_GATEWAY:
            {
                IoT::FindGatewayRespose findGatewayRespose;
                if (findGatewayRespose.ParseFromString( networkPackageResp.body()))
                {
                    for (int i = 0; i < findGatewayRespose.gatewayid().size(); ++i)
                    {
                        std::cout << " your gatewayids[" << i << "] = " << GREEN
                                  << findGatewayRespose.gatewayid().at( i ) << RESET << std::endl;
                    }
                }
                break;
            }

            case IOT_CREATE_DEVICE:
            {
                IoT::CreateDeviceRespose createDeviceRespose;

                if (createDeviceRespose.ParseFromString( networkPackageResp.body()))
                {
                    std::cout << " your Device id = " << GREEN << createDeviceRespose.deviceid() << RESET << std::endl;
                }
                break;
            }

            case IOT_GENERATE_DEVICE_TOKEN:
            {
                IoT::GenerateDeviceTokenRespose generateDeviceTokenRespose;
                if (generateDeviceTokenRespose.ParseFromString( networkPackageResp.body()))
                {
                    std::cout << " your new Token = " << GREEN << generateDeviceTokenRespose.token() << RESET
                              << std::endl;
                }
            }

        }
    } else if (networkPackageResp.type_m() == NetWork::NetWorkPackageModel::UNDEFINE)
    {
        switch (networkPackageResp.type_sub())
        {
            case 0:
            {
                std::cout << " Link Server " << GREEN << " Success " << RESET << std::endl;
            }
        }
    } else
    {
        // undefine
    }
    return 0;
}

static void chineseMENU()
{
    std::cout << BLUE << "Menu Type:" << RESET << std::endl
              << "0.  跳过本次操作 " << std::endl
              << "1.  注册账户" << std::endl
              << "2.  登录 " << std::endl
              << "3.  登出" << std::endl
              << "4.  (None)" << std::endl
              << "5.  修改密码" << std::endl
              << "6.  查找数据 " << std::endl
              << "7.  登录设备 " << std::endl
              << "8.  发送心跳包(None)" << std::endl
              << "9.  控制设备 " << std::endl
              << "10. 设备控制Ack" << std::endl
              << "11. 查找网关id " << std::endl
              << "12. 创建设备" << std::endl
              << "13. 生成新的 设备Token " << std::endl;
}
static void englistMENU(){
    std::cout << BLUE << "Menu Type:" << RESET << std::endl
              << "0.  pass " << std::endl
              << "1.  register" << std::endl
              << "2.  login " << std::endl
              << "3.  logout " << std::endl
              << "4.  (None)" << std::endl
              << "5.  change Password " << std::endl
              << "6.  FindData " << std::endl
              << "7.  LoginDevice " << std::endl
              << "8.  (None) " << std::endl
              << "9.  Control " << std::endl
              << "10. ControlAck " << std::endl
              << "11. findGateway " << std::endl
              << "12. CreatDevice " << std::endl
              << "13. GenDeviceToken " << std::endl;
}

/**
 * @brief 菜单功能表
 * @param outSendMessage , 需要发送的proto 序列化后的数据
 * @return 0 -- 可以发送  1 --- 忽略本次发送
 */
int MenuFunction(std::string &tempnetworkpack)
{
    // TODO 发送事件表
//    std::string tempnetworkpack;
    // 请求包
    NetWork::NetWorkPackageRequest netWorkPackageRequest;
    // TODO 发送事件表

    if (currentLangCode == CHINESE )
    {
        chineseMENU();
    } else if (currentLangCode == ENGLISH )
    {
        englistMENU();
    }



    int type = -1;
    char ch;

    std::cin >> type;
    while (! std::cin)
    {
        while ((ch = getchar ()) != '\n')
        continue;
        std::cout << "re input : ";
        std::cin.clear ();
        std::cin >> type;
    }
    std::cout <<"your type = "<<type<<std::endl;
    switch (type)
    {
        case 0:{
            return -1;
        }
        case 1:
        {
            Auth::RegisterAPI registerApi;
            std::string email, password, confirmPassword;
            std::cout << "doing register ... " << std::endl;
            username.clear();
            while (email.empty())
            {
                std::cout << "your email : " << email << std::endl;
                std::cin >> email;
            }
            while (username.empty())
            {
                std::cout << "your username : " << username << std::endl;
                std::cin >> username;
            }
            while (password.empty())
            {
                std::cout << "your password : " << password << std::endl;
                std::cin >> password;
            }


            while (confirmPassword != password)
            {
                std::cout << "input your password(confirm) :";
                std::cin >> confirmPassword;
            }

            registerApi.set_username( username );
            registerApi.set_email( email );
            registerApi.set_password( password );
            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::AuthMod );
            netWorkPackageRequest.set_type_sub( AUTH_REGISTER );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( registerApi.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }

        case 2:
        {
            std::cout << " doing login ..." << std::endl;
            std::string password;

            username.clear();
            password.clear();
            while (username.empty())
            {
                std::cout << " your username : " << username << std::endl;
                std::cin >> username;
            }
            while (password.empty())
            {
                std::cout << " your password : " << password << std::endl;
                std::cin >> password;
            }

            int64_t currtime = getTimeMilli();

            Auth::LoginRequest loginRequest;
            loginRequest.set_username( username );
            loginRequest.set_password( password );
            loginRequest.set_timestamp( currtime );

            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::AuthMod );
            netWorkPackageRequest.set_type_sub( AUTH_LOGIN );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( loginRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }
        case 3 :
        {
            std::cout << " doing logout ..." << std::endl;

            Auth::LogoutAPI logoutApi;
            if (token.empty())
            {
                std::cout << " no login ..." << std::endl;
                return 1;

            }
            logoutApi.set_token( token );
            logoutApi.set_timestamp( getTimeMilli());

            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::AuthMod );
            netWorkPackageRequest.set_type_sub( AUTH_LOGOUT );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( logoutApi.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }
        case 5 :
        {
            std::cout << " doing change Password ..." << std::endl;
            std::string password;
            while (password.empty())
            {
                std::cout << " your password : " << password << std::endl;
                std::cin >> password;
            }
            Auth::ChangePasswordRequest changePasswordRequest;
            changePasswordRequest.set_oldtoken( token );
            changePasswordRequest.set_newpassword( password );
            changePasswordRequest.set_timestamp( getTimeMilli());


            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::AuthMod );
            netWorkPackageRequest.set_type_sub( AUTH_CHANGE_PASSWORD );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( changePasswordRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }
        case 6:
        {
            //
//            string token = 1; // 用户 token
//            uint64 GatewayId = 2; // 网关id
//            uint64 DevideId = 3; // 终端id
//            int32 key = 4; // 键
//            int64 time = 5; // 时间
//            FindDirectionEnum direction = 6; //放向
//            int32 size = 7; // 数量

            uint64_t gid = 0, did = 0;
            int32_t key = 0, size = 1, direction = 0;
            int64_t currentTime = getTimeMilli();
            std::cout << " findData currtime(" << currentTime << ") " << std::endl;
            while (gid == 0)
            {
                std::cout << " input GatewayId : ";
                std::cin >> gid;
            }

            while (did == 0)
            {
                std::cout << " input DevideId : ";
                std::cin >> did;
            }

            std::cout << " input key(default 0 ) : ";
            std::cin >> key;

            if (key == 0)
            {
                while (!(direction == 1 || direction == 2) || direction == 0)
                {
                    std::cout << " input direction( 1 or 2 ) : ";
                    std::cin >> direction;
                }
                std::cout << " input size(default 1 ) : ";
                std::cin >> size;


                std::cout << " input time default is current:";
                std::cin >> currentTime;

            }

            IoT::FindSensorDataRequest findSensorDataRequest;

            findSensorDataRequest.set_token( token );
            findSensorDataRequest.set_gatewayid( gid );
            findSensorDataRequest.set_deviceid( did );
            findSensorDataRequest.set_key( key );

            findSensorDataRequest.set_direction((IoT::FindDirectionEnum) direction );
            findSensorDataRequest.set_size( size );

            findSensorDataRequest.set_time( currentTime );


            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );
            netWorkPackageRequest.set_type_sub( IOT_FIND_SENSOR_DATA );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( findSensorDataRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );

            break;
        }

        case 7:
        {
            //
            std::string inputToken;

            while (inputToken.empty())
            {
                std::cout << GREEN << " input Token : ";

                std::cin >> inputToken;
            }
            std::cout << RESET << " your Token = " << inputToken << std::endl;
            IoT::LoginDeviceAPI loginDeviceApi;
            loginDeviceApi.set_token( inputToken );
            loginDeviceApi.set_time( getTimeMilli());


            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );
            netWorkPackageRequest.set_type_sub( IOT_LOGIN_DEVICE );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( loginDeviceApi.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }
        case 8:
        {
            return -1;
        }

        case 9:
        {

            std::string controlToken, controlData;

            while (controlToken.empty())
            {
                std::cout << GREEN << " input Token : ";
                std::cin >> controlToken;
            }

            while (controlData.empty())
            {
                std::cout << GREEN << " input Data : ";
                std::cin >> controlData;
            }
            std::cout << RESET << " your Token = " << controlToken << " data = " << controlData << std::endl;

            IoT::ControlDeviceRequest controlDeviceRequest;

            controlDeviceRequest.set_token( controlToken );

            controlDeviceRequest.set_data( controlData );

            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );
            netWorkPackageRequest.set_type_sub( IOT_CONTROL_DEVICE );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( controlDeviceRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }

        case 10:
        {
            std::string taskCode, errmsg;

            int64_t errCode = 0;

            while (taskCode.empty())
            {
                std::cout << GREEN << " input TaskCode : ";
                std::cin >> taskCode;
            }

            while (errmsg.empty())
            {
                std::cout << GREEN << " input errmsg : ";
                std::cin >> errmsg;
            }

            while (errCode <= 0)
            {
                std::cout << GREEN << " input errCode : ";
                std::cin >> errCode;
            }

            IoT::ControlDeviceAckAPI controlDeviceAckApi;
            controlDeviceAckApi.set_taskcode( taskCode );
            controlDeviceAckApi.set_errcode( errCode );
            controlDeviceAckApi.set_errormsg( errmsg );

            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );
            netWorkPackageRequest.set_type_sub( IOT_CONTROL_ACK );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( controlDeviceAckApi.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );

            break;
        }

        case 11:
        {
            std::string myToken;

            std::cout << GREEN << " input YourToken( null ) : ";
            std::cin >> myToken;
            std::cout << RESET << " you Token = " << myToken << std::endl;

            IoT::FindGatewayRequest findGatewayRequest;

            findGatewayRequest.set_token( myToken );


            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );
            netWorkPackageRequest.set_type_sub( IOT_FIND_GATEWAY );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( findGatewayRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );
            break;
        }

        case 12 :
        {
            std::string note;
            uint64_t gatewayid = 0;
            int32_t permission = 0;
            while (note.empty())
            {
                std::cout << GREEN << " input note : ";
                std::cin >> note;
            }

            while (gatewayid == 0)
            {
                std::cout << GREEN << " input your getawayid : ";
                std::cin >> gatewayid;
            }

            while (permission == 0)
            {
                std::cout << GREEN << " input device permission : ";
                std::cin >> permission;
            }

            IoT::CreateDeviceRequest createDeviceRequest;
            createDeviceRequest.set_gatewayid( gatewayid );
            createDeviceRequest.set_note( note );
            createDeviceRequest.set_permission((IoT::DataPermissionEnum) permission );

            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );
            netWorkPackageRequest.set_type_sub( IOT_CREATE_DEVICE );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( createDeviceRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );


            break;
            // createDeviceRequest.set_token()
        }

        case 13 :
        {
            uint64_t gatewayid = 0;
            uint64_t deviceid = 0;


            while (gatewayid == 0)
            {
                std::cout << GREEN << " input your getawayid : ";
                std::cin >> gatewayid;
            }

            while (deviceid == 0)
            {
                std::cout << GREEN << " input deviceid : ";
                std::cin >> deviceid;
            }

            std::cout << "your input gatewayid = " << gatewayid << " deviceid = " << deviceid << std::endl;
            IoT::GenerateDeviceTokenRequest generateDeviceTokenRequest;

            generateDeviceTokenRequest.set_token( token );
            generateDeviceTokenRequest.set_gatewayid( gatewayid );
            generateDeviceTokenRequest.set_deviceid( deviceid );
            netWorkPackageRequest.set_type_m( NetWork::NetWorkPackageModel::IOTMod );

            netWorkPackageRequest.set_type_sub( IOT_GENERATE_DEVICE_TOKEN );
            netWorkPackageRequest.set_taskid( taskid_++ );
            netWorkPackageRequest.set_body( generateDeviceTokenRequest.SerializeAsString());
            netWorkPackageRequest.SerializePartialToString( &tempnetworkpack );

            break;
        }
        default:
        {
            return -1;
        }
    }

    // 结束
    return 0;

}

static void changeLangLanguage(){
    std::cout << "change Your Language : " <<std::endl
    << "1 , 中文" <<std::endl
    << "2 , Englist "<<std::endl
    <<">";
    int code = 0;


    while ( !(code ==1 ||code==2) )
    {
        std::cin >>code ;
    }
    currentLangCode = code ;
    std::cout <<"CHANGE "<<GREEN <<"SUCCESS" <<RESET <<std::endl;
    return;
}

static void handle_connection(int sockfd)
{
    char sendline[MAXLINE], recvline[MAXLINE];
//    uint8_t sendProtocolPackageBuff[MAXLINE];

    std::string sendProtocolPackage;
//    int maxfdp, stdineof;
    struct pollfd pfds[2];
    int n;
    pfds[0].fd = sockfd;
    pfds[0].events = POLLIN;
    pfds[1].fd = STDIN_FILENO;
    pfds[1].events = POLLIN;

    while (1)
    {
        //nfds：用来指定第一个参数数组元素个数: 2
        poll( pfds, 2, -1 );
        if (pfds[0].revents & POLLIN)
        {
            n = read( sockfd, recvline, MAXLINE );
            if (n == 0)
            {
                fprintf( stderr, "client: server is closed.\n" );
                close( sockfd );
            }
            // printf("recvline: %s", recvline);
            ResposePackageEvent((uint8_t *) recvline, n );
            // std::cout <<BOLDGREEN<<"client>>"<<RESET<<std::endl;
            write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m", sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );
        }
        if (pfds[1].revents & POLLIN)
        {
            // 命令行输入事件
            n = read( STDIN_FILENO, sendline, MAXLINE );
            // sendline 命令行输入的原文 , n 读取到的长度

            if (n == 0)
            {
                printf( "n==0\n" );
                shutdown( sockfd, SHUT_WR );
                continue;
            }
            // int32_t length = 0;
            std::string command( sendline, 4 ); // 读取命令
            if (command == "menu" || command == "MENU")
            {
                // 进入 功能表
                if (MenuFunction( sendProtocolPackage ) != 0)
                {
                    // 跳过
                    write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m",
                           sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );

                    continue;
                }

                if (sendProtocolPackage.length() == 0)
                {
                    write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m",
                           sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );
                    continue;
                }
            }else if (command == "quit" || command =="QUIT")
            {
                break;
            } else if (command == "help" || command == "HELP"){
                std::cout <<"Command List : "<<std::endl;
                std::cout <<"help/HELP"<<"\t\t\t" << "open  help "<<std::endl;
                std::cout <<"quit/QUIT"<<"\t\t\t" << "quit this program "<<std::endl;
                std::cout <<"menu/MENU"<<"\t\t\t" << "open  function List "<<std::endl;
                std::cout <<"lang/LANG"<<"\t\t\t" << "change Language "<<std::endl;
                write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m",
                       sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );

                continue;
            } else if (command == "LANG" || command =="lang"){
                changeLangLanguage();
                write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m",
                       sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );

                continue;
            } else {
                std::cout<< RED <<" Unsupported commands "<<RESET <<std::endl;
                std::cout<< YELLOW <<" You can input help "<<RESET <<std::endl;
                write( STDOUT_FILENO, "\033[1m\033[32mclient>>\033[0m",
                       sizeof( "\033[1m\033[32mclient>>\033[0m" ) - 1 );

                continue;
            }

            std::cout << YELLOW << "Request : " << StringToHex( sendProtocolPackage ) << RESET << std::endl;

            write( sockfd, sendProtocolPackage.c_str(), sendProtocolPackage.length());
        }
    }
}
